package com.hcm.module.gzfk.ctrl;

import com.hcm.kernel.mvc.ctrl.KernelCtrl;
import com.hcm.kernel.util.MD5Util;
import com.hcm.kernel.util.MyBigDecimal;
import com.hcm.kernel.util.RandomUtil;
import com.hcm.kernel.util.SystemConfig;
import com.hcm.kernel.wechat.MsgAPI;
import com.hcm.kernel.wechat.ProcessWeChatMsg;
import com.hcm.kernel.wechat.util.HttpUtil;
import com.hcm.module.admin.model.User;
import com.hcm.module.admin.service.IUserService;
import com.hcm.module.gzfk.ctrl.util.GAuthAPI;
import com.hcm.module.gzfk.ctrl.util.GPayAPI;
import com.hcm.module.gzfk.model.PayLog;
import com.hcm.module.gzfk.service.impl.PayLogService;
import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;
import org.jsoup.nodes.Document;
import org.jsoup.select.Elements;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.math.BigDecimal;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.List;

/**
 * 微信相关操作
 */
@Controller
@RequestMapping("/weChat")
public class WeChatCtrl extends KernelCtrl {
    private Logger log = LoggerFactory.getLogger(WeChatCtrl.class);

    @Autowired
    private IUserService userService;
    @Autowired
    PayLogService payLogService;

    /**
     * 处理微信请求
     * @param request
     * @param response
     * @throws Exception
     */
    @RequestMapping("/process")
    public void process(HttpServletRequest request,HttpServletResponse response) throws Exception {
        String result = "";
        /** 判断是否是微信接入激活验证，只有首次接入验证时才会收到echostr参数，此时需要把它直接返回 */
        String echostr = request.getParameter("echostr");
        if (echostr != null && echostr.length() > 1) {
            result = echostr;
        } else {
            /** 读取接收到的xml消息 */
            StringBuffer sb = new StringBuffer();
            InputStream is = request.getInputStream();
            InputStreamReader isr = new InputStreamReader(is, "UTF-8");
            BufferedReader br = new BufferedReader(isr);
            String s;
            while ((s = br.readLine()) != null) {
                sb.append(s);
            }
            String xml = sb.toString();    //次即为接收到微信端发送过来的xml数据
            log.info("WeChatCtrl.process-request:"+xml);
            //处理消息
            ProcessWeChatMsg msg = new ProcessWeChatMsg(xml);
            result = msg.getResult();
        }
        log.info("WeChatCtrl.process-result:"+result);
        response.getWriter().print(result);
    }

    @RequestMapping("/auth")
    public void auth(){
        GAuthAPI.auth();
    }
    /**
     * 微信授权成功后，回调接口，主要用来获取用户信息，一般包含openid    <br>
     * 唯一存在的问题，就是多次验证后，怎么登陆   <br>
     * 目前存在的问题为微信成功后为多次回调
     *
     * @param code 微信回调添加的参数code
     * @param mm
     * @return
     */
    @RequestMapping("/code")
    public String code(String code,ModelMap mm,HttpSession session){
        String json = GAuthAPI.getUserOpenid(code);//"{'openid':'op2cJuMSzWvOmIEHzv8VQX1-jM8c'}";//
        if(json.contains("openid")) {//如果含有errormsg说明错了。
            User user = userService.update(json);
            if (user != null) {
                if(user.getWeChatName() == null){
                    json = GAuthAPI.getUserInfo(user.getCode(),user.getAttr0());
                    if(json.contains("headimgurl"))
                        user = userService.update(json);
                }
            }
            mm.put("user", user);
            session.setAttribute("user", user);
        }
        return "redirect:/wx/index.htm";
    }

    /**
     * 下单
     * @param mm
     * @param pay
     * @return  op2cJuMSzWvOmIEHzv8VQX1-jM8c
     * http://localhost:8080/weChat/pay.htm?pay=10&openid=op2cJuMSzWvOmIEHzv8VQX1-jM8c
     */
    @RequestMapping("/pay")
    public String order(ModelMap mm,String pay,HttpSession session){
        Object obj = session.getAttribute("user");
        if(obj != null) {
            User user = (User)obj;
            if(user.getPay().compareTo(new BigDecimal(20))>0){
                MsgAPI.send(user.getCode(), "您当前余额已经大于￥20.00，吃的太多了，有点消化不良，想吐。。。过会儿再喂我吧！");
                return "redirect:/wx/index.htm";
            }

            int payment = Integer.parseInt(pay.replace("元", ""));
            String random = RandomUtil.random();
            String result = GPayAPI.pay(random, user.getCode(), String.valueOf(payment));

            //需要解析xml
            mm.put("pay", pay);
            mm.put("user", user);
            Document document = org.jsoup.Jsoup.parse(result);
            Elements elements = document.getElementsByTag("prepay_id");

            List<NameValuePair> nvps = new ArrayList<>();
            nvps.add(new BasicNameValuePair("appId", SystemConfig.getString("appid")));
            nvps.add(new BasicNameValuePair("nonceStr", RandomUtil.random()));
            nvps.add(new BasicNameValuePair("package", "prepay_id="+elements.text()));
            nvps.add(new BasicNameValuePair("signType", "MD5"));
            nvps.add(new BasicNameValuePair("timeStamp", System.currentTimeMillis()+""));
            String sign = HttpUtil.toUrl(nvps);
            sign = sign + "key="+ SystemConfig.getString("key");
            sign = MD5Util.encode(sign).toUpperCase();
            nvps.add(new BasicNameValuePair("paySign", sign));
            mm.put("nvps",nvps);
            user.setPay(user.getPay().add(new BigDecimal(payment)));
            session.setAttribute("user",user);//其实在这里并没有真正的充值呢，所以在这里将session变更是有一定的错误的

            //插入支付历史，只插入历史，并没有真正的变更页面数据
            PayLog payLog = new PayLog();
            payLog.setOpenId(user.getCode());
            payLog.setCreateTime(new Timestamp(System.currentTimeMillis()));
            payLog.setPay(new MyBigDecimal(payment));
            payLog.setPayNo(random);
            payLogService.add(payLog);
        }

        return "wx/module/zf";
    }

    /**
     * 配合上面的方法进行的，先发起支付，支付成后回调。
     * @param request
     * @throws Exception
     */
    @RequestMapping("/callBack")
    public void callback(HttpServletRequest request) throws Exception{
        /** 读取接收到的xml消息 */
        StringBuffer sb = new StringBuffer();
        InputStream is = request.getInputStream();
        InputStreamReader isr = new InputStreamReader(is, "UTF-8");
        BufferedReader br = new BufferedReader(isr);
        String s = "";
        while ((s = br.readLine()) != null) {
            sb.append(s);
        }
        String xml = sb.toString();    //次即为接收到微信端发送过来的xml数据
        log.info("WeChatCtrl.callBack:"+xml);
        Document document = org.jsoup.Jsoup.parse(xml);
        Elements elements = document.getElementsByTag("result_code");
        //out_trade_no订单号
        Elements tradeNo = document.getElementsByTag("out_trade_no");
        Elements openid = document.getElementsByTag("openid");
        Elements fee = document.getElementsByTag("total_fee");

        if(elements.text().equalsIgnoreCase("success")){
            User user = userService.pay(tradeNo.text(),openid.text());
            request.getSession().setAttribute("user",user);

            //发送消息
            MsgAPI.send(user.getCode(), "充值成功：恭喜您成功充值￥" + (Integer.parseInt(fee.text()) / 100) + "，充值后新余额为￥" + user.getPay() + "，可以开始干活了！");
        }else{//将失败的结果写表中
            payLogService.update(tradeNo.text(),elements.text());
        }
    }
}
